package ru.aslanov.schedule.model;

import ru.aslanov.schedule.server.InputLangUtil;

import javax.jdo.annotations.EmbeddedOnly;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import java.io.Serializable;

/**
 * @author Sergey Aslanov
 *         Created: Oct 12, 2010 1:47:48 PM
 */
@PersistenceCapable
@EmbeddedOnly
public class I18nString implements Serializable {
    private static final String[][] EMPTY_AR = new String[0][0];
    private static final String EQ_SIGN = "~";

    transient private String[][] i18nText = null;

    @Persistent
    private String dbValue;

    public I18nString() {
    }


    public void setValueWithThreadLang(String text) {
        if (i18nText == null) parseDbValue();
        
        final String lang = InputLangUtil.getThreadLocalInputLang();
        boolean found = false;
        for (String[] strings : i18nText) {
            if ((lang == null && strings[0] == null)
                    || lang != null && lang.equals(strings[0])) {
                strings[1] = text;
                found = true;
                break;
            }
        }
        if (!found) {
            String[][] newAr = new String[i18nText.length + 1][2];
            for (int i = 0; i < i18nText.length; i++) {
                System.arraycopy(i18nText[i], 0, newAr[i], 0, i18nText[i].length);
            }
            newAr[newAr.length-1][0] = lang;
            newAr[newAr.length-1][1] = text;
            i18nText = newAr;
        }
        formatDbValue();
    }


    public String getValueWithThreadLang() {
        if (i18nText == null) parseDbValue();
        
        final String lang = InputLangUtil.getThreadLocalInputLang();
        final String defLang = InputLangUtil.getThreadLocalDefaultInputLang();

        String value = null;
        boolean found = false;
        for (String[] strings : i18nText) {
            if (strings[1] != null) {
                if (value == null) {
                    value = strings[1];
                }
                if (defLang != null && defLang.equals(strings[0])) {
                    value = strings[1];
                }
            }
            if ((lang != null && lang.equals(strings[0]))
                    || (lang == null && strings[0] == null)) {
                value = strings[1];
                found = true;
                break;
            }
        }
        if (found) {
            return value;
        } else if (value != null) {
            return lang + "???{" + value + "}???";
        } else {
            return null;
        }

    }

    public void formatDbValue() {
        StringBuilder sb = new StringBuilder();
        for (String[] strings : i18nText) {
            if (sb.length() > 0) sb.append("|");
            if (strings[0] != null)
                sb.append(strings[0]).append(EQ_SIGN);
            if (strings[1] != null)
                sb.append(strings[1]);            
        }
        dbValue = sb.toString();
    }


    private void parseDbValue() {
        if (dbValue == null) {
            i18nText = EMPTY_AR;
            return;
        }
        final String defLang = InputLangUtil.getThreadLocalDefaultInputLang();

        final String[] strings = dbValue.split("\\|");
        i18nText = new String[strings.length][2];
        for (int i = 0; i < strings.length; i++) {
            String string = strings[i];
            int eq = string.indexOf(EQ_SIGN);
            if (eq > 0) {
                i18nText[i][0] = string.substring(0, eq);
                i18nText[i][1] = string.substring(eq + 1);
            } else {
                i18nText[i][0] = defLang;
                i18nText[i][1] = string;
            }
            if (i18nText[i][1] != null && i18nText[i][1].length() == 0)
                i18nText[i][1] = null;
        }
    }


    public String getValue(String lang) {
        if (i18nText == null) parseDbValue();
        for (String[] strings : i18nText) {
            if ((lang == null && strings[0] == null)
                    || (lang != null && lang.equals(strings[0]))) {
                return strings[1];
            }
        }
        return null;
    }

    public static void main(String[] args) {
        I18nString i18nString = new I18nString();

        System.out.println("dbValue = " + i18nString.dbValue);
        System.out.println("value = " + i18nString.getValueWithThreadLang());
        i18nString.setValueWithThreadLang("No lang yet");
        System.out.println("dbValue = " + i18nString.dbValue);
        System.out.println("value = " + i18nString.getValueWithThreadLang());

        InputLangUtil.setThreadLocalInputLang("en", null);
        i18nString.setValueWithThreadLang("English");
        InputLangUtil.setThreadLocalInputLang("es", null);
        i18nString.setValueWithThreadLang("Spain");
        System.out.println("dbValue = " + i18nString.dbValue);
        System.out.println("value = " + i18nString.getValueWithThreadLang());

        String dbValue = i18nString.dbValue;

        i18nString = new I18nString();
        i18nString.dbValue = dbValue;
        i18nString.parseDbValue();
        System.out.println("dbValue = " + i18nString.dbValue);
        System.out.println("value = " + i18nString.getValueWithThreadLang());

        InputLangUtil.setThreadLocalInputLang("jp", null);
        System.out.println("value = " + i18nString.getValueWithThreadLang());

        InputLangUtil.setThreadLocalInputLang("jp", "en");
        System.out.println("value = " + i18nString.getValueWithThreadLang());

        InputLangUtil.setThreadLocalInputLang(null, "en");
        System.out.println("value = " + i18nString.getValueWithThreadLang());

        InputLangUtil.setThreadLocalInputLang(null, null);
        System.out.println("value = " + i18nString.getValueWithThreadLang());


        InputLangUtil.setThreadLocalInputLang(null, "ru");
        i18nString = new I18nString();
        i18nString.dbValue = dbValue;
        i18nString.parseDbValue();
        System.out.println("dbValue = " + i18nString.dbValue);
        System.out.println("value = " + i18nString.getValueWithThreadLang());

        i18nString.setValueWithThreadLang("Some");
        System.out.println("dbValue = " + i18nString.dbValue);
        System.out.println("value = " + i18nString.getValueWithThreadLang());

        InputLangUtil.setThreadLocalInputLang("ru", "ru");
        i18nString.setValueWithThreadLang("Russian");
        System.out.println("dbValue = " + i18nString.dbValue);
        System.out.println("value = " + i18nString.getValueWithThreadLang());
    }

}
